home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / debugaid.arc / DEBUG.TXT next >
Text File  |  1989-06-08  |  35KB  |  670 lines

  1.                                      DEBUG
  2.  
  3.  
  4.      This  tutorial is made to present an overview of the DEBUG.COM program for
  5. the IBM PC.   This utility can be extremely useful, when used correctly.  It is
  6. almost  a  must for Assembler Language programmers,  and can  also  provide  an
  7. insight  into  the operation of the machine at the bit level.   It has  several
  8. nice features, including the ability to display and change any of the registers
  9. in the IBMPC, start and stop program execution at any time, change the program,
  10. and  look  at diskettes,  sector by sector.   DEBUG works at the  machine  code
  11. level,  but it does also have the ability to disassemble machine code,  and (at
  12. dos 2.0), assemble instructions directly into machine code.
  13.  
  14.      The  procedure for starting DEBUG and command syntax will not  be  covered
  15. here,  as they are well documented in the DOS manual.   What we will do is show
  16. some examples of the various commands and the response which is expected.  Note
  17. that the segment registers will probably not be exactly what is shown.  This is
  18. normal, and should be expected.
  19.  
  20.      For  the examples,  I will be using the demo program CLOCK.COM in the  XA4
  21. database.   For  those of you with the IBM assembler (MASM),  the source can be
  22. down loaded.   If you do not have the assembler, or have another assembler, the
  23. file  CLOCK.HEX has been up loaded.   It can be converted to a .COM file  using
  24. any of the existing HEX conversion programs on the SIG.  See the file CLOCK.DOC
  25. for more information.
  26.  
  27.  
  28.  
  29.                                 STARTING DEBUG
  30.  
  31.      There are two ways to start DEBUG with a file.  Both ways produce the same
  32. results, and either can be used.
  33.  
  34.      In the Command Line:  A>debug clock.com <ENTER>
  35.  
  36.      Separate from the command line:  A>debug <ENTER>
  37.                                       -n clock.com
  38.                                       -l
  39.  
  40.      With either method,  you will get the DEBUG prompt of a hyphen (-).  DEBUG
  41. has loaded your program and is ready to run.   The description of each instruc-
  42. tion will assume this as a starting point,  unless otherwise mentioned.   If at
  43. any time you get different results,  check your procedure carefully.   If it is
  44. correct,  please leave me a message.   I have tried to check everything,  but I
  45. have been known to make a mistake or two (anyway).
  46.  
  47.      If you do have problems,  you can enter the command Q (Quit) any time  you
  48. have the DEBUG prompt (-).  This should return you to the DOS prompt.
  49.  
  50.  
  51.                                 RUNNING DEBUG
  52.  
  53.                                DISPLAY COMMANDS
  54.  
  55.  
  56.                                Register command
  57.  
  58.      The first thing we should look at are the registers,  using the R command.
  59. If  you type in an R with no parameters,  the registers should be displayed  as
  60. so:
  61.  
  62. AX=0000  BX=0000  CX=0446  DX=0000  SP=FFFE  BP=0000  SI=0000  DI=0000
  63. DS=6897  ES=6897  SS=6897  CS=6897  IP=0100   NV UP DI PL NZ NA PE NC
  64. 6897:0100 E96B01        JMP     026E
  65.  
  66.      CX  contains  the length of the file (0446h or 1094d).   If the file  were
  67. larger  than 64K,  BX would contain the high order of the size.   This is  very
  68. important to remember when using the Write command,  as this is the size of the
  69. file to be written.   Remember,  once the file is in memory,  DEBUG has no idea
  70. how large the file is,  or if you may have added to it.   The amount of data to
  71. be written will be taken from the BX and CX registers.
  72.  
  73.      If  we want to change one of the registers,  we enter R and  the  register
  74. name.  Let's place 1234 (hexadecimal) in the AX register:
  75.  
  76.      -R AX          R and AX register
  77.      AX 0000        Debug responds with register and contents
  78.      : 1234         : is the prompt for entering new contents.  We respond 1234
  79.      -              Debug is waiting for the next command.
  80.  
  81.      Now if we display the registers, we see the following:
  82.  
  83. AX=1234  BX=0000  CX=0446  DX=0000  SP=FFFE  BP=0000  SI=0000  DI=0000
  84. DS=6897  ES=6897  SS=6897  CS=6897  IP=0100   NV UP DI PL NZ NA PE NC
  85. 6897:0100 E96B01        JMP     026E
  86.  
  87. Note that nothing has changed,  with the exception of the AX register.  The new
  88. value has been placed in it,  as we requested.  One note.  The Register command
  89. can only be used for 16 bit registers (AX,  BX,  etc.).  It cannot change the 8
  90. bit registers (AH,  AL,  BH,  etc.).  To change just AH, for instance, you must
  91. enter the the data in the AX register, with your new AH and the old AL values.
  92.  
  93.  
  94.                                  Dump command
  95.  
  96.      One of the other main features of DEBUG is the ability to display areas of
  97. storage.   Unless you are real good at reading 8088 machine language,  the Dump
  98. command is mostly used to display data (text,  flags,  etc.).  To display code,
  99. the Unassemble command below is a better choice.   If we enter the Dump command
  100. at this time,  DEBUG will default to the start of the program.   It uses the DS
  101. register as it's default,  and,  since this is a .COM file,  begins at DS:0100.
  102. It will by default display 80h (128d) bytes of data, or the length you specify.
  103. The  next  execution of the Dump command will display the following 80h  bytes,
  104. and so on.   For example, the first execution of D will display DS:0100 for 80h
  105. bytes,  the next one DS:0180 for 80h bytes,  etc.   Of course, absolute segment
  106. and  segment register overrides can be used,  but only hex numbers can be  used
  107. for the offset,e D will display DS:0100 for 80h
  108. bytes,  the next one DS:0180 for 80h bytes,  etc.   Of course, absolute segment
  109. and  segment register overrides can be used,  but only hex numbers can be  used
  110. for the offset.  That is, D DS:BX is invalid.
  111.  
  112.      With our program loaded, if we enter the Dump command, we will see this:
  113.  
  114. 6897:0100  E9 6B 01 43 4C 4F 43 4B-2E 41 53 4D 43 6F 70 79   ik.CLOCK.ASMCopy
  115. 6897:0110  72 69 67 68 74 20 28 43-29 20 31 39 38 33 4A 65   right (C) 1983Je
  116. 6897:0120  72 72 79 20 44 2E 20 53-74 75 63 6B 6C 65 50 75   rry D. StucklePu
  117. 6897:0130  62 6C 69 63 20 64 6F 6D-61 69 6E 20 73 6F 66 74   blic domain soft
  118. 6897:0140  77 61 72 65 00 00 00 00-00 00 00 00 00 00 00 00   ware............
  119. 6897:0150  00 00 00 00 00 00 00 00-00 24 00 00 00 00 00 00   .........$......
  120. 6897:0160  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
  121. 6897:0170  00 00 00 00 00 00 00 00-00 00 00 00 44 4F 53 20   ............DOS
  122.  
  123.      Notice that the output from the Dump command is divided into three  parts.
  124. On the left, we have the address of the first byte on the line.  This is in the
  125. format Segment:Offset.
  126.  
  127.      Next  comes the  hex data at that location.   Debug will always start  the
  128. second line at a 16 byte boundary; that is, if you entered D 109, you would get
  129. 7  bytes of information on the first line (109-10F),  and the second line would
  130. start at 110.   The last line of data would have the remaining 9 bytes of data,
  131. so 80h bytes are still displayed.
  132.  
  133.      The third area is the ASCII representation of the data.  Only the standard
  134. ASCII  character set is displayed.   Special characters for the IBMPC  are  not
  135. displayed;  rather periods (.) are shown in their place.   This makes searching
  136. for plain text much easier to do.
  137.  
  138.      Dump can be used to display up to 64K bytes of data, with one restriction:
  139. It cannot cross a segment boundary.   That is,  D 0100 l f000 is valid (display
  140. DS:0100  to  DS:F0FF),  but  D 9000 l 8000 is not (8000h +9000h  =  11000h  and
  141. crosses a segment boundary).
  142.  
  143.      Since  64K  is 10000h and cannot fit into four hex characters,  Dump  uses
  144. 0000 to indicate 64K.  To display a complete segment, enter D 0 l 0.  This will
  145. display the total 64K segment.
  146.  
  147.      If,  at  any time you want to suspend the display  of  data,  Cntl-NumLock
  148. works as usual.   If you want to terminate the display, Cntl-Break will stop it
  149. and return you to the DEBUG prompt.
  150.  
  151.  
  152.  
  153.                                     Search
  154.  
  155.      Search  is  used  to find the occurrence of a specific byte or  series  of
  156. bytes  within a segment.   The address parameters are the same as for the  Dump
  157. command, so we will not duplicate them here.  However, we also need the data to
  158. be searched for.   This data can be entered as either hexadecimal or  character
  159. data.   Hexadecimal  data is entered as bytes,  with a space or a comma as  the
  160. separator.   Character  data is enclosed by single or double quotes.   Hex  and
  161. character data can be mixed in the same request,  i.e. S 0 l 100 12 34 'abc' 56
  162. is  valid,  and requests a search from DS:0000 through DS:00FF for the sequence
  163. of 12h 34h a b c 56h,  in that order.  Upper case characters are different than
  164. lower  case  characters,  and a match will not be found if the  case  does  not
  165. match.   For  instance,  'ABC'  is not the same as 'abc' or 'Abc' or any  other
  166. combination of upper and lower case characters.  However, 'ABC' is identical to
  167. "ABC", since the single and double quotes are separators only.
  168.  
  169.      An example is looking for the string 'Sat'.  Here's what would happen:
  170.  
  171.      -S 0 l 0 'Sat'
  172.      6897:0235
  173.      -
  174. Again,  the  actual segment would be different in your system,  but the  offset
  175. should be the same.   If we then displayed the data,  we would find the  string
  176. 'Saturday'  at this location.   We could also search on 'turda',  or any  other
  177. combination  of characters in the string.   If we wanted to find every place we
  178. did an Int 21h (machine code for Int is CD), we would do the following:
  179.  
  180.      -S 0 l 0 cd 21
  181.      6897:0050
  182.      6897:0274
  183.      6897:027F
  184.      6897:028B
  185.      6897:02AD
  186.      6897:02B4
  187.      6897:0332
  188.      6897:0345
  189.      6897:034C
  190.      6897:043A
  191.      6897:0467
  192.      6897:047A
  193.      6897:0513
  194.      6897:0526
  195.      6897:0537
  196.      6897:0544
  197.      -
  198.  
  199. DEBUG found the hex data CD 21 at the above locations.  This does not mean that
  200. all these addresses are INT 21's, only that that data was there.  It could (and
  201. most likely is) an instruction,  but it could also be an address, the last part
  202. of a JMP instruction,  etc.  You will have to manually inspect the code at that
  203. area to make sure it is an INT 21.   (You don't expect the machine to do every-
  204. thing, do you?).
  205.  
  206.  
  207.                                 Compare command
  208.  
  209.      Along  the  same lines of Dump and Search commands,  we have  the  Compare
  210. command.   Compare  will take two blocks of memory and compare them,  byte  for
  211. byte.  If the two addresses do not contain the same information, both addresses
  212. are displayed,  with their respective data bytes.   As an example, we will com-
  213. pare DS:0100 with DS:0200 for a length of 8.
  214.  
  215.      -d 0100 l 8 0200
  216.      6897:0100  E9  65  6897:0200
  217.      6897:0101  6B  70  6897:0201
  218.      6897:0102  01  74  6897:0202
  219.      6897:0103  43  65  6897:0203
  220.      6897:0104  4C  6D  6897:0204
  221.      6897:0105  4F  62  6897:0205
  222.      6897:0106  43  65  6897:0206
  223.      6897:0107  4B  72  6897:0207
  224.  
  225.      None of the eight bytes compared,  so we got output for each byte.   If we
  226. had gotten a match on any of the bytes, DEBUG would have skipped that byte.  if
  227. all of the locations requested matched,  DEBUG would have simply responded with
  228. another prompt.   No other message is displayed.   This is useful for comparing
  229. two blocks of data from a file,  or a program with the BIOS ROM.   Otherwise, I
  230. have not found a great amount of use for it.
  231.  
  232.  
  233.  
  234.                               Unassemble command
  235.  
  236.      For  debugging,  one of the main commands you will use is  the  Unassemble
  237. command.   This  command will take machine code and convert it to instructions.
  238. Addressing is the same as for previous commands with one exception:   Since  we
  239. are  now  working with code (the previous commands are mainly  for  data),  the
  240. default register is the CS register.  In a .COM program, this makes very little
  241. difference,  unless  you reset the DS register yourself.   However,  in a  .EXE
  242. file,  it  can make a lot of difference,  as the CS and DS registers are set to
  243. different values.
  244.  
  245.      Unassemble data can lead to some interesting results.   For  instance,  in
  246. our example,  CS:IP is set to 6897:0100.   If we look at the program,  we see a
  247. JMP as the first instruction,  followed by data.   If we just enter U,  we will
  248. start at CS:IP (6897:0100) and start unassembling data.   What we will get is a
  249. good instruction, followed by more or less nonsense.  For instance:
  250.  
  251.      -U
  252.      6897:0100 E96B01        JMP     026E
  253.      6897:0103 43            INC     BX
  254.      6897:0104 4C            DEC     SP
  255.      6897:0105 4F            DEC     DI
  256.      6897:0106 43            INC     BX
  257.      6897:0107 4B            DEC     BX
  258.  
  259. And so on,  through 6897:011D.   We know the INC BX, DEC SP, etc. are not valid
  260. instructions,  but  DEBUG doesn't,  so we do have to look at the  code.   After
  261. working with DEBUG a little, you will be able to spot code versus data with the
  262. Unassemble  command.   For now,  suffice to say that the first instruction will
  263. take us to CS:026E and we can start from there.
  264.  
  265.      If we Unassemble CS:026E, we will find something which looks a little more
  266. like what we expect.  We get:
  267.  
  268.      -U 26E
  269.      6897:026E 8D167802      LEA     DX,[0278]
  270.      6897:0272 B409          MOV     AH,09
  271.      6897:0274 CD21          INT     21
  272.      6897:0276 EB05          JMP     027D
  273.      6897:0278 1B5B32        SBB     BX,[BP+DI+32]
  274.      6897:027B 4A            DEC     DX
  275.      6897:027C 24B4          AND     AL,B4
  276.      6897:027E 30CD          XOR     CH,CL
  277.      6897:0280 213C          AND     [SI],DI
  278.      6897:0282 027D0A        ADD     BH,[DI+0A]
  279.      6897:0285 8D167C01      LEA     DX,[017C]
  280.      6897:0289 B409          MOV     AH,09
  281.      6897:028B CD21          INT     21
  282.      6897:028D CD20          INT     20
  283.  
  284.  
  285.      The first few instructions look fine.   But,  after the JMP  027D,  things
  286. start to look a little funny.  Also, note that there is no instruction starting
  287. at 027D.   We have instructions at 027C and 027E,  but not 027D.  This is again
  288. because DEBUG doesn't know data from instructions.  At 027C, we should (and do)
  289. have the end of our data.   But, this also translates into a valid AND instruc-
  290. tion,  so DEBUG will treat it as such.   If we wanted the actual instruction at
  291. 027D,  we could enter U 027D and get it,  but from here,  we don't know what it
  292. is.   what I'm trying to say is,  DEBUG will do what ever you tell it.   If you
  293. tell it to Unassemble data,  it will do so to the best of its ability.  So, you
  294. have to make sure you have instructions where you think you do.
  295.  
  296.  
  297.                               DATA ENTRY COMMANDS
  298.  
  299.                                      Enter
  300.  
  301.      The  Enter command is used to place bytes of data in memory.   It has  two
  302. modes:  Display/Modify  and  Replace.   The difference is in where the data  is
  303. specified - in the Enter command itself, or after the prompt.
  304.  
  305.      If you enter E address alone,  you are in display/modify mode.  DEBUG will
  306. prompt  you  one  byte at a time,  displaying the current byte  followed  by  a
  307. period.   At this time,  you have the option of entering one or two hexadecimal
  308. characters.   If you hit the space bar, DEBUG will not modify the current byte,
  309. but  go on to the next byte of data.   If you go too far,  the hyphen (-)  will
  310. back up one byte each time it is pressed.
  311.  
  312.      E 103
  313.      6897:0103  43.41   4C.42   4F.43   43.     4B.45
  314.      6897:0108  2E.46   41.40   53.-
  315.      6897:0109  40.47   53.
  316.  
  317. In this example,  we entered E 103.   DEBUG responded with the address and  the
  318. information  at  that  byte (43).   We entered the 41 and  DEBUG  automatically
  319. showed the next byte of data (4C).  Again, we entered 42, debug came back.  The
  320. next byte was 4F, we changed it to 43.  At 106, 43 was fine with us, so we just
  321. hit the space bar.  DEBUG did not change the data, and went on to the following
  322. bytes.  After entering 40 at location 109, we found we had entered a bad value.
  323. The  hyphen  key was pressed,  and DEBUG backed up  one  byte,  displaying  the
  324. address and current contents.  Note that it has changed from the original value
  325. (41)  to  the value we typed in (40).   We then type in the correct  value  and
  326. terminate by pressing the ENTER key.
  327.  
  328.      As you can see,  this can be very awkward,  especially where large amounts
  329. of data are concerned.   Also, if you need ASCII data, you have to look up each
  330. character  and enter its hex value.   Not easy,  to be sure.   That's where the
  331. Replace  mod  of operation comes in handy.   Where the Display/Modify  mode  is
  332. handy  for  changing a few bytes at various offsets,  the Replace mode  is  for
  333. changing  several  bytes of information at one time.   Data can be  entered  in
  334. hexadecimal or character format,  and multiple bytes can be entered at one time
  335. without  waiting  for the prompt.   If you wanted to store the  characters  'My
  336. name' followed by a hexadecimal 00 starting at location 103, you would enter:
  337.  
  338.      E 103 'My name' 0
  339.  
  340. As  in  the Search command,  data can be entered in character  (in  quotes)  or
  341. hexadecimal  forms  and  can be mixed in the same command.   This is  the  most
  342. useful way of entering large amounts of data into memory.
  343.  
  344.  
  345.                                      Fill
  346.  
  347.      The Fill command is useful for storing a lot of data of the same data.  It
  348. differs  from  the Enter command in that the list will be  repeated  until  the
  349. requested amount of memory is filled.  If the list is longer than the amount of
  350. memory to be filled,  the extra items are ignored.   Like the Enter command, it
  351. will  take hexadecimal or character data.   Unlike the Enter  command,  though,
  352. large amounts of data can be stored without specifying every character.   As an
  353. example, to clear 32K (8000h) of memory to 00h, you only need to enter:
  354.  
  355.      F 0 L 8000 0
  356.  
  357. Which translates into Fill, starting at DS:0000 for a Length of 32K (8000) with
  358. 00h.   If the data were entered as '1234',  the memory would be filled with the
  359. repeating string '123412341234',  etc.   Usually,  it is better to enter  small
  360. amounts of data with the Enter command,  because an error in the length parame-
  361. ter of the Fill command can destroy a lot of work.  The Enter command, however,
  362. will  only change the number of bytes actually entered,  minimizing the effects
  363. of a parameter error.
  364.  
  365.  
  366.                                      Move
  367.  
  368.      The Move command does just what it says - it moves data around inside  the
  369. machine.   It  takes  bytes from with the starting address and moves it to  the
  370. ending address.   If you need to add an instruction into a program,  it can  be
  371. used  to make room for the instruction.   Beware,  though.   Any data or labels
  372. referenced after the move will not be in the same place.   Move can be used  to
  373. save a part of the program in free memory while you play with the program,  and
  374. restore  it  at any time.   It can also be used to copy ROM BIOS  into  memory,
  375. where it can be written to a file or played with to your heart's content.   You
  376. can then change things around in BIOS without having to worry about programming
  377. a ROM.
  378.  
  379.      M 100 L 200 ES:100
  380.  
  381. This  will  move the data from DS:0100 to DS:02FF (Length 200) to  the  address
  382. pointed to by ES:0100.  Later, if we want to restore the data, we can say:
  383.  
  384.      M ES:100 L 200 100
  385.  
  386. which will move the data back to its starting point.   Unless the data has been
  387. changed while at the temporary location (ES:0100),  we will restore the data to
  388. its original state.
  389.  
  390.                                    Assemble
  391.  
  392. I purposely left the Assemble command to the end,  as it is the most complex of
  393. the  data entry commands.   It will take the instructions in the assembler lan-
  394. guage and convert them to machine code directly.   Some of the things it  can't
  395. do,  however,  are: reference labels, set equates, use macros, or anything else
  396. which cannot be translated to a value.  Data locations have to be referenced by
  397. the physical memory address, segment registers, if different from the defaults,
  398. must be specified,  and RET instructions must specify the type (NEAR or FAR) of
  399. return to be used.   Also,  if an instruction references data but not registers
  400. (i.e.  Mov [278],5), the Byte ptr or Word ptr overrides must be specified.  One
  401. other  restriction:   To tell DEBUG the difference between moving 1234h into AX
  402. and  moving  the data from location 1234 into AX,  the latter is coded  as  Mov
  403. AX,[1234],  where the brackets indicate the reference is an addressed location.
  404. The differences between MASM and DEBUG are as follows:
  405.  
  406.      MASM                DEBUG                    Comments
  407.  
  408.      Mov  AX,1234        Mov  AX,1234             Place 1234 into AX
  409.      Mov  AX,L1234       Mov  AX,[1234]           Contents of add. 1234 to AX
  410.      Mov  AX,CS:1234     CS:Mov AX,[1234]         Move from offset of CS.
  411.      Movs Byte ptr ...   Movesb                   Move byte string
  412.      Movs Word ptr ...   Movsw                    Move word string
  413.      Ret                 Ret                      Near return
  414.      Ret                 Retf                     Far return
  415.  
  416. Also,  Jmp instructions will be assembled automatically to Short,  Near, or Far
  417. Jmps.  However, the Near and Far operands can be used to override the displace-
  418. ment if you do need them.  Let's try a very simple routine to clear the screen.
  419.  
  420.      -A 100
  421.      6897:0100 mov ax,600
  422.      6897:0103 mov cx,0
  423.      6897:0106 mov dx,184f
  424.      6897:0109 mov bh,07
  425.      6897:010B int 10
  426.      6897:010D int 20
  427.      6897:010F
  428.      -
  429.  
  430.      We  are using BIOS interrupt 10h,  which is the video interrupt.  (If  you
  431. would like more information on the interrupt,  there is a very good description
  432. in  the Technical Reference Manual.)  We need to call BIOS with  AX=600,  BH=7,
  433. CX=0, and DX=184Fh.  First we had to load the registers, which we did at in the
  434. first  four instructions.   The statement at offset 6897:010B  actually  called
  435. BIOS.   The INT 20 at offset 010D is for safety only.  We really don't need it,
  436. but with it in,  the program will stop automatically.   Without the INT 20, and
  437. if  we did not stop,  DEBUG would try and execute whatever occurs at 010F.   If
  438. this  happens  to  be a valid program (unlikely),  we would  just  execute  the
  439. program.   Usually,  though,  we will find it to be invalid,  and will probably
  440. hang the system,  requiring a cntl-alt-del (maybe) or a power-off and on  again
  441. (usually).  So, be careful and double check your work!
  442.  
  443.      Now, we need to execute the prograAoihead,  and will probably
  444. hang the system,  requiring a cntl-alt-del (maybe) or a power-off and on  again
  445. (usually).  So, be careful and double check your work!
  446.  
  447.      Now, we need to execute the program.  To do this, enter the G command, a G
  448. followed  by  the enter key.   If you have entered the program  correctly,  the
  449. screen  will  clear and you will get a message "Program  terminated  normally".
  450. (More on the Go command later).
  451.  
  452.      Again, I cannot stress the importance of checking your work when using the
  453. Assemble  command.   The commands may assemble correctly,  but cause a  lot  of
  454. problems.   This  is especially important for the Jmp and Call commands;  since
  455. they  cause  an interruption in the flow of the program,  they  can  cause  the
  456. program  to jump into the middle of an instruction,  causing VERY unpredictable
  457. results.
  458.  
  459.  
  460.                                  I/O commands
  461.  
  462.                                      Name
  463.  
  464. The  Name  command has just one purpose - specifying the name of a  file  which
  465. DEBUG is going to Load or Write.  It does nothing to change memory or execute a
  466. program,  but does prepare a file control block for DEBUG to work with.  If you
  467. are going to load a program,  you can specify any parameters on the same  line,
  468. just  like in DOS.   One difference is,  the extension MUST be specified.   The
  469. default is no extension.   DEBUG will load or write any file, but the full file
  470. name must be entered.
  471.  
  472.      -n chkdsk.com /f
  473.  
  474. This statement prepares DEBUG for loading the program CHKDSK.COM passing the /f
  475. switch to the program.   When the Load (see below) command is  executed,  DEBUG
  476. will  load CHKDSK.COM and set up the parameter list (/f) in the program's input
  477. area.
  478.  
  479.  
  480.                                      Load
  481.  
  482.      The Load command has two formats.  The first one will load a program which
  483. has been specified by the Name command into storage, set the various registers,
  484. and prepare for execution.   Any program parameters in the Name command will be
  485. set into the Program Segment Prefix,  and the program will be ready to run.  If
  486. the  file is a .HEX file,  it is assumed to have valid  hexadecimal  characters
  487. representing  memory  values,  two hexadecimal characters per byte.  Files  are
  488. loaded  starting at CS:0100 or at the address specified in the  command.    For
  489. .COM.  .HEX and .EXE files,  the program will be loaded, the registers set, and
  490. CS:IP  set  to the first instruction in the  program.   For  other  files,  the
  491. registers are undetermined, but basically, the segment registers are set to the
  492. segment of the PSP (100h bytes before the code is actually loaded),  and BX and
  493. CX are set to the file length.  Other registers are undetermined
  494.  
  495.      -n clock.com
  496.      -l
  497.  
  498.  
  499. This  sequence  will load clock.com into memory,  set IP to the entry point  of
  500. 0100,  and CX will contain 0446, the hexadecimal size of the file.  The program
  501. is now ready to run.
  502.  
  503.      The second form of the Load command does not use the Name command.   It is
  504. used  to load absolute sectors from the disk (hard or soft) into  memory.   The
  505. sector count starts with the first sector of track 0 and continuing to the  end
  506. of the track.   The next sector is track 0,  second side (if double sided), and
  507. continues to the end of that sector.   Then,  back to the first side,  track 1,
  508. and so on,  until the end of the disk.   Up to 80h (128d) sectors can be loaded
  509. at  one time.   To use,  you must specify starting address,  drive  (0=A,  1=B,
  510. etc.), starting sector, and number of sectors to load.
  511.  
  512.      -l 100 0 10 20
  513.  
  514. This instruction tells DEBUG to load, starting at DS:0100, from drive A, sector
  515. 10h  for 20h sectors. drive  (0=A,  1=B,
  516. etc.), starting sector, and number of sectors to load.
  517.  
  518.  
  519. This instruction tells DEBUG to load, starting at DS:0100, from drive A, sector
  520. 10h  for 20h sectors.   DEBUG can sometimes be used this way to recover part of
  521. the  information on a damaged sector.   If you get an error,  check the  memory
  522. location  for that data.   Often times,  part of the data has been  transferred
  523. before  the error occurs and the remainder (especially for text files)  can  be
  524. manually entered.   Also,  repetitive retrys will sometimes get the information
  525. into  memory.   This can then be rewritten on the same diskette (see the  Write
  526. command below), or copied to the same sector on another diskette.  In this way,
  527. the data on a damaged disk can sometimes be recovered.
  528.  
  529.  
  530.                                      Write
  531.  
  532.      The  write  command is very similar to the Load command.   Both  have  two
  533. modes of operation, and both will operate on files or absolute sectors.  As you
  534. have  probably guessed,  the Write command is the opposite of the Load command.
  535. Since all the parameters are the same,  we will not cover the syntax in detail.
  536. However,  one  thing worth mentioning:  When using the file mode of  the  Write
  537. command,  the  amount of data to be written is specified in BX and CX,  with BX
  538. containing the high-order file size.   The start address can be specified or is
  539. defaulted to CS:0100.   Also, files with an extension of .EXE or .HEX cannot be
  540. written  out,  and error message to that effect will be displayed.   If you  do
  541. need  to  change a .EXE or .HEX file,  simply rename and  load  it,  make  your
  542. changes, save it and name it back to its original filename.
  543.  
  544.      -
  545.  
  546. This is the Line input port for the first Asynchronous adapter.   Your data may
  547. be different,  as it depends on the current status of the port.   It  indicates
  548. the  data  in the register at the time it was read was 7Dh.   Depending on  the
  549. port, this data may change, as the ports are not controlled by the PC.
  550.  
  551.  
  552.                                     Output
  553.  
  554.      As you can probably guess,  the Output command is the reverse of the Input
  555. command.   You  can use the Output command to send a single byte of data  to  a
  556. port.   Note  that certain ports can cause the system to hang (especially those
  557. dealing with system interrupts and the keyboard),  so be careful with what  you
  558. send where!
  559.  
  560.      -o 3fc 1
  561.      -
  562.  
  563. Port 3FCh is the modem control register for the first asynchronous port.  Send-
  564. ing a 01h to this port turns on the DTR (Data Terminal Ready) bit.   A 00h will
  565. turn all the bits off.   If you have a modem which indicates this bit,  you can
  566. watch the light flash as you turn the bit on and off.
  567.  
  568.  
  569.                               EXECUTION COMMANDS
  570.  
  571.                                       Go
  572.  
  573.      The  Go  command  is used to start program execution.   A  very  versatile
  574. command, it can be used to start the execution at any point in the program, and
  575. optionally  stop  at any of ten points (breakpoints) in  the  program.   If  no
  576. breakpoints  are set (or the breakpoints are not executed),  program  execution
  577. continues  until  termination,  in which case the message  "Program  terminated
  578. normally" is sent.   If a breakpoint is executed,  program execution stops, the
  579. current registers are displayed, and the DEBUG prompt is displayed.  Any of the
  580. DEBUG commands can be executed, including the Go command to continue execution.
  581. Note  that the Go command CANNOT be terminated by Cntl-break.   This is one  of
  582. the few commands which cannot be interrupted while executing.
  583.  
  584.      -g =100
  585.  
  586. The  Go command without breakpoints starts program execution at the address (in
  587. this  case  CS:0100)  in the command.   The equal sign before  the  address  is
  588. required.   (Without the equal sign, the address is taken as a breakpoint.)  If
  589. no starting address is specified,  program execution starts at CS:IP.   In this
  590. case,  since  no breakpoints are specified,  CLOCK.COM will continue  execution
  591. until the cntl-break key is pressed and the program terminates.   At this time,
  592. you will get the message "Program terminated normally".   Note that,  after the
  593. termination  message,  the  program should be reloaded before  being  executed.
  594. Also,  any memory alterations (storing data,  etc.) will not be restored unless
  595. the program is reloaded.
  596.  
  597.      -g 276 47c 528 347
  598.  
  599. This version of the control command will start the program and set  breakpoints
  600. at  CS:276,  CS:47C,  CS:528  and  CS:347.   These correspond to  locations  in
  601. CLOCK.COM  after the screen is cleared,  and the day,  date and time  are  dis-
  602. played,  respectively.   The  program will stop at whichever breakpoint it hits
  603. first.   Note  that the second and third breakpoints will only be displayed  at
  604. two times - when the program is started and at midnight.   If you care to  stay
  605. up (or just change the time in the computer),  and set a breakpoint at 47C,  t
  606. will stop when the program is started, and again at midnight.
  607.  
  608.      Some notes about breakpoints. The execution stops just before the instruc-
  609. tion is executed.  Setting a breakpoint at the current instruction address will
  610. not execute any instructions.  DEBUG will set the breakpoint first, then try to
  611. execute the instruction, causing another breakpoint.  Also, the breakpoints use
  612. Interrupt  3 to stop execution.   DEBUG intercepts interrupt 3 to stop the pro-
  613. gram execution and display the registers.   Finally,  breakpoints are not saved
  614. between Go commands.  Any breakpoints you want will be have to be set with each
  615. Go command.
  616.  
  617.  
  618.                                      Trace
  619.  
  620.      Along the same lines as Go is the Trace command.   The difference is that,
  621. while Go executes a whole block of code at one time, the Trace command executes
  622. instructions  one at a time,  displaying the registers after each  instruction.
  623. Like the Go instruction,  execution can be started at any address.   The  start
  624. address again must be preceeded by an equal sign.   However,  the Trace command
  625. also has a parameter to indicate how many instructions are to be executed.
  626.  
  627.      -t =100 5
  628.  
  629. This Trace command will start at CS:100 and execute five instructions.  Without
  630. the  address,  execution will start at the current CS:IP value and continue for
  631. five instructions.  T alone will execute one instruction.
  632.  
  633.      When using Trace to follow a program, it is best to go around calls to DOS
  634. and interrupts,  as some of the routines involved can be  lengthy.   Also,  DOS
  635. cannot be Traced,  and doing so has a tendency to hang the system.   Therefore,
  636. Trace  to  the call or interrupt and Go to the next address after the  call  or
  637. interrupt.
  638.  
  639.  
  640.                               ARITHMETIC COMMANDS
  641.  
  642.                                  Hexarithmetic
  643.  
  644.      The  Hexarithmetic command is handy for adding and subtracting hexadecimal
  645. numbers.  It has just two parameters - the two numbers to be added and subtrac-
  646. ted.   DEBUG's response is the sum and difference of the numbers.   The numbers
  647. can be one to four hexadecimal digits long.   The addition and subtraction  are
  648. unsigned, and no carry or borrow is shown beyond the fourth (high order) digit.
  649.  
  650.      -h 5 6
  651.      000B FFFF
  652.      -h 5678 1234
  653.      68AC 4444
  654.      -
  655.  
  656. In  the  first example,  we are adding 0005 and 0006.   The sum  is  000B,  the
  657. difference  is -1.   However,  since there is no carry,  we get FFFF.   In  the
  658. second example, the sum of 5678 and 1234 is 68AC, and the difference is 4444.
  659.  
  660.  
  661.                                     WRAPUP
  662.  
  663.      If  you give it a chance,  DEBUG can be a very useful tool for the  IBMPC.
  664. It  is  almost a requirement for debugging assembler language programs,  as  no
  665. nice  error  messages are produced at run time.   DEBUG does work at  the  base
  666. machine  level,  so you need some experience to use it  effectively,  but  with
  667. practice, it will be your most useful assembler language debugging tool.
  668.  
  669.  
  670.